package wiView.console;

import java.awt.Color;
import java.util.HashMap;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import wiBase.WiObject;
import wiBase.baseInterface.OnOutputStreamListener;
import wiBase.baseObject.Event;
import wiBase.baseObject.Node;
import wiBase.baseObject.Packet;
import wiModel.WiModelAdapter;

public class WiObjectOutputStream implements OnOutputStreamListener {

    JScrollPane jpn_console;
    JTextPane console;
    JScrollBar scrVertical;
    wiEngine.WiEngine engine;
    Document doc;
    // format text
    SimpleAttributeSet attDef = new SimpleAttributeSet();
    SimpleAttributeSet attType = new SimpleAttributeSet();
    SimpleAttributeSet attTime = new SimpleAttributeSet();
    SimpleAttributeSet attPacket = new SimpleAttributeSet();
    SimpleAttributeSet attNode = new SimpleAttributeSet();
    StringBuilder txtConsole = new StringBuilder();
    
    private boolean traceDefault = true;
    public HashMap<String, Boolean> mapTraceEvent = null;
    public HashMap<Integer, OnOutputStreamListener> mapTraceNode = null;
    public HashMap<String, OnOutputStreamListener> mapTracePacket = null;

    public WiObjectOutputStream(JScrollPane scroll, JTextPane console) {
	this.jpn_console=scroll;
	this.console=console;
	
	initComponent();
	
	//setTraceEvent();
    }

    private void initComponent() {
	engine = wiEngine.WiEngine.getInstance();
	
	mapTraceEvent = new HashMap<>();
	mapTraceNode = new HashMap<>();
	mapTracePacket = new HashMap<>();

	mapTraceEvent.put("send", traceDefault);
	mapTraceEvent.put("forward", traceDefault);
	mapTraceEvent.put("receive", traceDefault);
	mapTraceEvent.put("move", traceDefault);
	mapTraceEvent.put("sleep", traceDefault);
	mapTraceEvent.put("wake", traceDefault);
	mapTraceEvent.put("drop", traceDefault);
	mapTraceEvent.put("broastcast", traceDefault);
	
	scrVertical = jpn_console.getVerticalScrollBar();
	doc = console.getDocument();
	setFont();
    }
//    public void setTraceEvent(String type, boolean isOn) {
//	mapTraceEvent.put(type, isOn);
//    }
    public void setTraceEvent(OnOutputStreamListener listener) {
	boolean eSend = mapTraceEvent.get("send");
	boolean eReceive = mapTraceEvent.get("receive");
	boolean eForward = mapTraceEvent.get("forward");
	boolean eMove = mapTraceEvent.get("move");
	boolean eSleep = mapTraceEvent.get("sleep");
	boolean eWake = mapTraceEvent.get("wake");
	boolean eDrop = mapTraceEvent.get("drop");
	boolean eBroastcast = mapTraceEvent.get("broastcast");

//	engine.addTraceEvent("send", null);
//	engine.addTraceEvent("receive", null);
//	engine.addTraceEvent("forward", null);
//	engine.addTraceEvent("move", null);
//	engine.addTraceEvent("sleep", null);
//	engine.addTraceEvent("wake", null);
//	engine.addTraceEvent("drop", null);
//	engine.addTraceEvent("broastcast", null);

	if (eSend) {
	    engine.addTraceEvent("send", listener);
	}
	if (eReceive) {
	    engine.addTraceEvent("receive", listener);
	}
	if (eForward) {
	    engine.addTraceEvent("forward", listener);
	}
	if (eMove) {
	    engine.addTraceEvent("move", listener);
	}
	if (eSleep) {
	    engine.addTraceEvent("sleep", listener);
	}
	if (eWake) {
	    engine.addTraceEvent("wake", listener);
	}
	if (eDrop) {
	    engine.addTraceEvent("drop", listener);
	}
	if (eBroastcast) {
	    engine.addTraceEvent("broastcast", listener);
	}

    }
    public void setConsole(JTextPane textPane) {
	console = textPane;
    }

    @Override
    public void write(String type, WiObject... seriable) {
	
	if (seriable[0] instanceof Event) {
	    try {
		txtConsole.append("\n").append(seriable[0].toString());

		setTextFormat(seriable[0]);

		scrVertical.setValue(scrVertical.getMaximum());
		Thread.sleep(0);
	    } catch (NullPointerException | InterruptedException | ArrayIndexOutOfBoundsException e) {
		System.out.println(e.toString());
	    }

	}
	if (seriable.length > 1) {
	    if (seriable[1] instanceof Node) {
		txtConsole.append("\n").append(seriable[1].toString());
	    } else if (seriable[1] instanceof Packet) {
		txtConsole.append("\n").append(seriable[1].toString());
	    }
	}
    }

    private void setFont() {
	int fontSizeDefault = 14;

	StyleConstants.setFontSize(attDef, fontSizeDefault);
	StyleConstants.setForeground(attDef, Color.white);

	StyleConstants.setFontSize(attType, fontSizeDefault);
	StyleConstants.setForeground(attType, Color.green);

	StyleConstants.setFontSize(attTime, fontSizeDefault);
	StyleConstants.setForeground(attTime, Color.yellow);

	StyleConstants.setFontSize(attPacket, fontSizeDefault);
	StyleConstants.setForeground(attPacket, Color.white);

	StyleConstants.setFontSize(attNode, fontSizeDefault);
	StyleConstants.setForeground(attNode, Color.yellow);
    }

    public void setTextFormatParse() {
	WiModelAdapter adapter = engine.getAdapter();
	String fileTrace = adapter.getFileTrace();
	String fileConf = adapter.getFileConfig();
	String duration = adapter.getDurationSimulation() + "";
	String width = adapter.getWidth() + "";
	String timeParse = adapter.getMilliTimeParse() + "";
	String length = adapter.getLength() + "";

	try {
	    doc.remove(0, doc.getLength());
	    doc.insertString(doc.getLength(), "File trace:\t " + fileTrace + "\n", attType);
	    doc.insertString(doc.getLength(), "File config:\t " + fileConf + "\n", attTime);
	    doc.insertString(doc.getLength(), "Duration:\t " + duration + "\n", attPacket);
	    doc.insertString(doc.getLength(), "Width:\t " + width + "\n", attTime);
	    doc.insertString(doc.getLength(), "Time parse:\t " + timeParse + "\n", attPacket);
	    doc.insertString(doc.getLength(), "Length:\t " + length + "\n", attTime);
	    doc.insertString(doc.getLength(), "-----------Parse File Complete----------" + "\n", attDef);

	} catch (BadLocationException ex) {
	    ex.printStackTrace();
	}
    }

    private void setTextFormat(WiObject object) {
	try {
	    doc.remove(0, doc.getLength());
	    doc.insertString(doc.getLength(), object.toString(), attType);
//	    doc.insertString(doc.getLength(), "Type:\t " + ((Event) object).type + "\n", attType);
//	    doc.insertString(doc.getLength(), "Time:\t " + ((Event) object).time + "\n", attTime);
//	    doc.insertString(doc.getLength(), "Packet Id:\t " + ((Event) object).packetId + "\n", attPacket);
//	    doc.insertString(doc.getLength(), "-----------Event Info----------" + "\n", attDef);
//	    doc.insertString(doc.getLength(), "Event: " + ((Event) object).toString(), attDef);

	} catch (BadLocationException ex) {
	    ex.printStackTrace();
	}
    }
}
